package com.yonyougov.cruxtestcase.testcase.baiscdata.enumvalue.multiversion;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonyougov.cruxtestcase.component.CommonLogin;
import com.yonyougov.cruxtestcase.component.ZWCDInvoke;
import com.yonyougov.cruxtestcase.dto.BaseResponseDto;
import com.yonyougov.cruxtestcase.dto.BaseTestReqDto;
import com.yonyougov.cruxtestcase.testcase.baiscdata.enumvalue.multiversion.dto.EnumValueAddDto;
import com.yonyougov.cruxtestcase.testcase.baiscdata.enumvalue.multiversion.dto.EnumValueDto;
import com.yonyougov.cruxtestcase.testcase.baiscdata.enumvalue.multiversion.dto.EnumValueHistoryDto;
import com.yonyougov.cruxtestcase.testcase.baiscdata.enumvalue.multiversion.dto.EnumValueSensitiveDto;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class EnumValueCaseService {
    private final ZWCDInvoke zwcdInvoke;
    private final CommonLogin commonLogin;
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

    private final String HEADER_FUNCTION_ID="x-function-id";
    private final String FUNCTION_ID_VALUE="57";
    private final String HEADER_TOKEN="Authorization";
    private final String queryInterfaceUrl ="/crux-basicdata/api/enumvalue";
    private final String updateInterfaceUrl ="/crux-basicdata/api/enumvalue?fetchProperties=*,region[id,lastModifiedVersion,code,name,type],parent[id,lastModifiedVersion,code,name,type]";
    private final String changeInterfaceUrl ="/crux-basicdata/api/enumvalue/change?fetchProperties=*,region[id,lastModifiedVersion,code,name,type],parent[id,lastModifiedVersion,code,name,type]";


    public EnumValueCaseService(ZWCDInvoke zwcdInvoke, CommonLogin commonLogin, RestTemplate restTemplate, ObjectMapper objectMapper) {
        this.zwcdInvoke = zwcdInvoke;
        this.commonLogin = commonLogin;
        this.restTemplate = restTemplate;
        this.objectMapper = objectMapper;
    }

    BaseResponseDto noSensitiveTestCase(EnumValueDto baseDto) {
        //1.拿到登录的Token
        BaseResponseDto baseResponseDto = new BaseResponseDto();
        String baseUrl = zwcdInvoke.getBaseUrl(baseDto.getEnvName());
        if (!StringUtils.isEmpty(baseUrl)) {
            String token = commonLogin.getToken(baseUrl, baseDto.getUser(), baseDto.getPassword());
            if (StringUtils.isNotBlank(token)) {
                //2.取接口参数，拼接完整url
                String serviceUrl=baseUrl+queryInterfaceUrl;
                serviceUrl=this.addParams2Url(serviceUrl,baseDto);

                HttpHeaders headers=new HttpHeaders();
                //Auth2 token 格式
                headers.set(HEADER_TOKEN,"Bearer " + token);
                headers.set(HEADER_FUNCTION_ID,FUNCTION_ID_VALUE);
                ResponseEntity<Object> response = restTemplate.exchange(serviceUrl, HttpMethod.GET,
                        new HttpEntity<>(headers), Object.class);

                //3.处理接口返回结果
                this.handleNoSensitiveQueryResponse(baseResponseDto,response);
            } else {
                baseResponseDto.setSuccess(false);
                baseResponseDto.setErrorMsg("码值不敏感查询接口调用失败！");
            }
        } else {
            baseResponseDto.setSuccess(false);
            baseResponseDto.setErrorMsg("环境不存在");
        }
        return baseResponseDto;
    }

    BaseResponseDto SensitiveTestcase(EnumValueSensitiveDto baseDto) {
        BaseResponseDto baseResponseDto = new BaseResponseDto();
        String baseUrl = zwcdInvoke.getBaseUrl(baseDto.getEnvName());
        if (!StringUtils.isEmpty(baseUrl)) {
            String token = commonLogin.getToken(baseUrl, baseDto.getUser(), baseDto.getPassword());
            if (StringUtils.isNotBlank(token)) {
                //2.取接口参数，拼接完整url
                String serviceUrl=baseUrl+queryInterfaceUrl;
                serviceUrl=this.addParams2Url(serviceUrl,baseDto);

                HttpHeaders headers=new HttpHeaders();
                //Auth2 token 格式
                headers.set(HEADER_TOKEN,"Bearer " + token);
                headers.set(HEADER_FUNCTION_ID,FUNCTION_ID_VALUE);
                ResponseEntity<Object> response = restTemplate.exchange(serviceUrl, HttpMethod.GET,
                        new HttpEntity<>(headers), Object.class);

                //3.处理接口返回结果
                this.handleSensitiveQueryResponse(baseResponseDto,response);
            } else {
                baseResponseDto.setSuccess(false);
                baseResponseDto.setErrorMsg("码值不敏感查询接口调用失败！");
            }
        } else {
            baseResponseDto.setSuccess(false);
            baseResponseDto.setErrorMsg("环境不存在");
        }
        return baseResponseDto;
    }

    /**
     * 查询敏感数据接口返回结果处理
     * @param baseResponseDto
     * @param response
     */
    private void handleSensitiveQueryResponse(BaseResponseDto baseResponseDto, ResponseEntity<Object> response) {
        if (response.getStatusCode() == HttpStatus.OK && response.hasBody()) {
            Object responseDto = response.getBody();
            assert responseDto != null;
            try {
                Object enumValueDto = objectMapper.readValue(objectMapper.writeValueAsString(response.getBody()),
                        Object.class);
                List<?> list = (List) enumValueDto;
                for (Object object : list) {
                    LinkedHashMap map = (LinkedHashMap) object;
                    String endDate = (String) map.get("endDate");
                    Date date=new SimpleDateFormat("yyyyMMdd").parse(endDate);
                    if(!(endDate != null && date.equals(new SimpleDateFormat("yyyyMMdd").format("20991231")))){
                        baseResponseDto.setSuccess(false);
                        baseResponseDto.setErrorMsg("接口返回数据不是敏感数据");
                        baseResponseDto.setData("enumValueDtoList", enumValueDto);
                        return;
                    }
                }
                baseResponseDto.setSuccess(true);
                baseResponseDto.setData("enumValueDtoList", enumValueDto);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
    }

    public BaseResponseDto queryHistoryTestcase(EnumValueHistoryDto baseDto) {
        //1.拿到登录的Token
        BaseResponseDto baseResponseDto = new BaseResponseDto();
        String baseUrl = zwcdInvoke.getBaseUrl(baseDto.getEnvName());
        if (!StringUtils.isEmpty(baseUrl)) {
            String token = commonLogin.getToken(baseUrl, baseDto.getUser(), baseDto.getPassword());
            if (StringUtils.isNotBlank(token)) {
                //2.取接口参数，拼接完整url
                String serviceUrl=baseUrl+queryInterfaceUrl;
                serviceUrl=this.addParams2Url(serviceUrl,baseDto);

                HttpHeaders headers=new HttpHeaders();
                //Auth2 token 格式
                headers.set(HEADER_TOKEN,"Bearer " + token);
                headers.set(HEADER_FUNCTION_ID,FUNCTION_ID_VALUE);
                ResponseEntity<Object> response = restTemplate.exchange(serviceUrl, HttpMethod.GET,
                        new HttpEntity<>(headers), Object.class);

                //3.处理接口返回结果
                this.handleQueryHistoryResponse(baseResponseDto,response);
            } else {
                baseResponseDto.setSuccess(false);
                baseResponseDto.setErrorMsg("码值历史数据查询接口调用失败！");
            }
        } else {
            baseResponseDto.setSuccess(false);
            baseResponseDto.setErrorMsg("环境不存在");
        }
        return baseResponseDto;
    }

    /**
     * 处理查询历史码值数据接口返回结果
     * TODO:当前表中只有几条数据是多版本数据，所以判断会出错
     * @param baseResponseDto 测试用例需要返回的对象
     * @param response 调用业务接口返回的结果
     */
    private void handleQueryHistoryResponse(BaseResponseDto baseResponseDto, ResponseEntity<Object> response) {
        if (response.getStatusCode() == HttpStatus.OK && response.hasBody()) {
            Object responseDto = response.getBody();
            assert responseDto != null;
            try {
                Object enumValueDto = objectMapper.readValue(objectMapper.writeValueAsString(response.getBody()),
                        Object.class);
                List<?> list = (List) enumValueDto;
                List newList=new ArrayList(list);
                for (int i = 1; i < list.size(); i++) {
                    Map newObj = (Map) list.get(i);
                    Map old = (Map) list.get(i - 1);
                    if (newObj.get("name").equals(old.get("name"))){
                        newList.remove(i-1);
                        newList.remove(i);
                    }
                }
                if (newList.size()>list.size()/2){
                    baseResponseDto.setSuccess(false);
                    baseResponseDto.setErrorMsg("接口未返回所有历史版本数据！");
                    baseResponseDto.setData("enumValueDtoList", enumValueDto);
                    return;
                }
                baseResponseDto.setSuccess(true);
                baseResponseDto.setData("enumValueDtoList", enumValueDto);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 处理查询不敏感码值数据接口返回结果
     * @param baseResponseDto 测试用例需要返回的对象
     * @param response 调用业务接口返回的结果
     */
    private void handleNoSensitiveQueryResponse(BaseResponseDto baseResponseDto,ResponseEntity<Object> response){
        if (response.getStatusCode() == HttpStatus.OK && response.hasBody()) {
            Object responseDto = response.getBody();
            assert responseDto != null;
            try {
                Object enumValueDto = objectMapper.readValue(objectMapper.writeValueAsString(response.getBody()),
                        Object.class);
                List<?> list = (List) enumValueDto;
                for (Object object : list) {
                    LinkedHashMap map = (LinkedHashMap) object;
                    String id = (String) map.get("id");
                    String did = (String) map.get("did");
                    if(!did.equals(id)){
                        baseResponseDto.setSuccess(false);
                        baseResponseDto.setErrorMsg("接口返回数据的did！=id,不是不敏感数据");
                        baseResponseDto.setData("enumValueDtoList", enumValueDto);
                        return;
                    }
                }
                baseResponseDto.setSuccess(true);
                baseResponseDto.setData("enumValueDtoList", enumValueDto);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 拼接接口参数到url
     * @param url 原来的url
     * @param dto 待拼接参数对象
     * @return 拼接后的完整url
     */
    private String addParams2Url(String url, BaseTestReqDto dto) {
        Field[] fields = dto.getClass().getDeclaredFields();
        StringBuilder requestURL = new StringBuilder(url);
        requestURL.append("?");
        boolean flag = true;
        String property="";
        String value="";
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            // 允许访问私有变量
            field.setAccessible(true);
            // 属性名
            property = field.getName();
            // 属性值
            try {
                value = field.get(dto).toString();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if (i != 0) {
                requestURL.append("&");
            }
            requestURL.append(property).append("=").append(value);
        }
        return requestURL.toString();
    }

    BaseResponseDto addTestcase(EnumValueAddDto baseDto) {
        BaseResponseDto baseResponseDto = new BaseResponseDto();
        String baseUrl = zwcdInvoke.getBaseUrl(baseDto.getEnvName());
        if (!StringUtils.isEmpty(baseUrl)) {
            String token = commonLogin.getToken(baseUrl, baseDto.getUser(), baseDto.getPassword());
            if (StringUtils.isNotBlank(token)) {
                //2.取接口参数，拼接完整url
                String serviceUrl=baseUrl+updateInterfaceUrl;
                //serviceUrl=this.addParams2Url(serviceUrl,baseDto);

                HttpHeaders headers=new HttpHeaders();
                //Auth2 token 格式
                headers.set(HEADER_TOKEN,"Bearer " + token);
                headers.set(HEADER_FUNCTION_ID,FUNCTION_ID_VALUE);
                ResponseEntity<Object> response = restTemplate.exchange(serviceUrl, HttpMethod.POST,
                        new HttpEntity<>(baseDto,headers), Object.class);

                //3.处理接口返回结果
                this.handleAddResponse(baseResponseDto,response,baseDto);
            } else {
                baseResponseDto.setSuccess(false);
                baseResponseDto.setErrorMsg("码值不敏感查询接口调用失败！");
            }
        } else {
            baseResponseDto.setSuccess(false);
            baseResponseDto.setErrorMsg("环境不存在");
        }
        return baseResponseDto;
    }

    private void handleAddResponse(BaseResponseDto baseResponseDto, ResponseEntity<Object> response,BaseTestReqDto baseDto) {
        if (response.getStatusCode() == HttpStatus.OK && response.hasBody()) {
            Object responseDto = response.getBody();
            assert responseDto != null;
            EnumValueAddDto dto = (EnumValueAddDto) baseDto;
            try {
                Object enumValueDto = objectMapper.readValue(objectMapper.writeValueAsString(response.getBody()),
                        Object.class);
                List<?> list = (List) enumValueDto;
                for (Object object : list) {
                    LinkedHashMap map = (LinkedHashMap) object;
                    String id = (String) map.get("id");
                    if(!dto.getId().equals(id)){
                        baseResponseDto.setSuccess(false);
                        baseResponseDto.setErrorMsg("接口返回数据不是新增数据，新增接口调用失败");
                        baseResponseDto.setData("enumValueDtoList", enumValueDto);
                        return;
                    }
                }
                baseResponseDto.setSuccess(true);
                baseResponseDto.setData("enumValueDtoList", enumValueDto);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
    }
}
